#include "dominion.h"
#include "dominion_helpers.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <assert.h>
#include "rngs.h"

#define NOISY_TEST 1

char CARD_NAMES[27][20] = {
    "curse", "estate", "duchy", "province", "copper",
    "silver", "gold", "adventurer", "council room",
    "feast", "gardens", "mine", "remodel", "smithy",
    "village", "baron", "great hall", "minion", "steward",
    "tribute", "ambassador", "cutpurse", "embargo",
    "outpost", "salvager", "sea hag", "treasure_map"
};

int in_list(int element, int* list, int size) {
    int i;
    for (i = 0; i < size; i++) {
        if (element == list[i]) {
            return i;
        }
    }
    return -1;
}

int random_card(int* list, int pile) {
    int card;
    if (pile == -1) {
        pile = rand() % 3;
    }
    switch(pile) {
        case 0:
            card = rand() % 3 + 1;
            break;
        case 1:
            card = rand() % 3 + 4;
            break;
        case 2:
            card = list[rand() % 10];
            break;
    }
    return card;
}

int random_kingdom_card() {
    return (rand() % 21) + 6;
}

void randomize_kingdom_cards(int* k) {
    int i = 0;
    int randCard;
    while(i<10) {
        randCard = random_kingdom_card();
        if (in_list(randCard, k, 10) == -1) {
            k[i] = randCard;
            i++;
        }
    }
    k = kingdomCards(k[0], k[1], k[2], k[3], k[4], k[5], k[6], k[7], k[8], k[9]);
}

int get_choices(int* choices, int card, int* k, int* hand, int hand_size) {
    int i;
    int no_choices[18] = {0,1,2,3,4,5,6,7,8,10,13,14,16,19,21,23,25,26};
    for (i=0; i<3; i++) {
        choices[i] = 0;
    }
    if (in_list(card, no_choices, 18) == 0) {
        switch(card) {
            case feast:
                choices[0] = random_card(k, -1);
                break;
            case mine:
                if (in_list(4, hand, hand_size)) {
                    choices[0] = in_list(4, hand, hand_size);
                    choices[1] = random_card(k, 1);
                } else if (in_list(5, hand, hand_size)) {
                    choices[0] = in_list(5, hand, hand_size);
                    choices[1] = random_card(k, 1);
                } else if (in_list(6, hand, hand_size)) {
                    choices[0] = in_list(6, hand, hand_size);
                    choices[1] = random_card(k, 1);
                } else {
                    return -1;
                }
                break;
            case remodel:
                choices[0] = rand() % hand_size;
                choices[1] = random_card(k, -1);
                break;
            case baron:
                choices[0] = 1;
                break;
            case minion:
                choices[0] = (rand() % 2) + 1;
            case steward:
                choices[0] = (rand() % 3) + 1;
                if (choices[0] == 3) {
                    choices[1] = rand() % hand_size;
                    choices[2] = rand() % hand_size;
                    while(choices[1] == choices[2]) {
                        choices[2] = rand() % hand_size;
                    }
                }
                break;
            case ambassador:
                choices[0] = rand() % hand_size;
                choices[1] = 1;
                for (i=0;i<hand_size; i++) {
                    if ((i != choices[0]) && (hand[i] == hand[choices[0]])) {
                        choices[1] = 2;
                    }
                }
                break;
            case embargo:
                choices[0] = random_card(k, -1);
                break;
            case salvager:
                choices[0] = rand() % hand_size;
                break;
        }
    }
    return 0;
}


int main () {
    int k[10] = {0};
    int choices[3] = {0};
    int i;
    int card;
    int numPlayers;
    struct gameState G;
    int tries;
    int success;
    int winners[MAX_PLAYERS];
    int x = 0;
    while(x<10000) {
    srand(time(NULL));
    randomize_kingdom_cards(k);
    printf("Testing dominion run through\n");
    if (NOISY_TEST) {
        fprintf(stderr, "Kingdom Cards:\n");
        for (i=0; i<10; i++) {
            fprintf(stderr, "%s\n", CARD_NAMES[k[i]]);
        }
        fprintf(stderr, ".............begin.................\n");
    }
    numPlayers = (rand() % 3) + 2;
    newGame();
    initializeGame(numPlayers, k, 1, &G);
    while(isGameOver(&G) == 0) {
        for (i=0; i<numHandCards(&G); i++) {
            if (G.numActions == 0) {
                break;
            }
            card = G.hand[G.whoseTurn][i];
            if (card > 6) {
                if (get_choices(
                        choices, card, k, G.hand[G.whoseTurn],
                        G.handCount[G.whoseTurn]) == 0) {
                    success = playCard(
                        i, choices[0], choices[1], choices[2], &G);
                    if ((success == 0) && NOISY_TEST) {
                        fprintf(stderr, "player %d played %s\n",
                               G.whoseTurn, CARD_NAMES[card]);
                    }
                }
            }
        }
        tries = 20;
        while (G.numBuys && tries) {
            card = random_card(k, -1);
            success = buyCard(card, &G);
            if ((success == 0) && NOISY_TEST) {
                fprintf(stderr, "player %d bought %s\n", G.whoseTurn,
                       CARD_NAMES[card]);
            }
            tries--;
        }
        if (NOISY_TEST) {
            fprintf(stderr, "...........end player %d's turn................\n", G.whoseTurn);
        }
        endTurn(&G);
    }
    if (NOISY_TEST) {
        for (i=0; i<numPlayers; i++) {
            fprintf(stderr,"player %d's card count %d\n", i, fullDeckCount(i, 0, &G));
            fprintf(stderr,"player %d's score %d\n", i, scoreFor(i, &G));
            fprintf(stderr, "......................\n");
        }
    }
    getWinners(winners, &G);
    if (NOISY_TEST) {
        for (i = 0; i<MAX_PLAYERS; i++) {
            if (winners[i] == 1) {
                fprintf(stderr, "<<<<....player %d won!....>>>>\n", i);
            }
        }
    }
    printf("Game run through successful\n");
    x++;
    }
    return 0;
}
